package com.wch.swh;

import java.util.ArrayList;
import java.util.Random;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity4 extends Activity {

	//상수 설정
	//핸들러로 들어온 메시지를 식별하기 위해
	//BUTTON관련 상수는 은 각 버튼의 아이디로 해당 버튼이 눌렸으니 다시 원상복귀하라는거고
	//STOP_THREAD 상수는 버튼 원상복귀했으니 다음 버튼 보여주거나 아니면 your turn으로 바꾸라는 거
	//NEW_GAME_ID는 게임 시작 후 생기는 메뉴.. 아이디 정해준 것
	private final int BUTTON_1 = 0;          
	private final int BUTTON_2 = 1;
	private final int BUTTON_3 = 2;
	private final int BUTTON_4 = 3;
	private final int STOP_THREAD = 4;
	private final int NEW_GAME_ID = 100;
	
	private TextView   score_board;   //점수 보여주는 텍스트
	private TextView   level_board;   //레벨 카운트 보여주는 텍스트
	private TextView   next_turn;     //컴터턴인지 사용자턴인지
	private ImageView  btn1;          
	private ImageView  btn2;
	private ImageView  btn3;
	private ImageView  btn4;
	private Button     startBtn;
	
	private PullThread pullThread;    //버튼이 눌렸다가 원상복귀 후 몇초간의 sleep을 주기위한 쓰레드 
	private PushThread pushThread;    //버튼이 sleep 없이 바로 눌리게 되면 같은 버튼이 눌릴경우 눌렸다가 떼지고 다시 눌리는게 아니라
	                                  //그냥 몇초가 눌릴상태로 멈춰진 모습처럼 보임
	
	private int level_count = 1;
	private int score = 0;
	private ArrayList<Integer> saveOrderOfCom = new ArrayList<Integer>();  // 난수를 발생하여 저장해 두었다가 컴퓨터가 버튼 눌린 모습을 화면에 뿌려줄때 값을 하나씩 꺼내서 쓰는 것
	private ArrayList<Integer> saveOrderOfUsr = new ArrayList<Integer>();  // 난수를 발생하여 저장해 두었다가 유저가 버튼을 눌렀을때 값을 하나씩 꺼내어서 비교 후 정답을 맞췄는지 비교하려고 쓰는 것
	                                                                       // Com, Usr 리스트는 결론적으로 둘은 같은 값을 가짐. index 값을 줘서 하려다가 복잡해서 걍 두개 만듬.
	                                                                       
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        initLayout();
        initScore();
    }
    
    public void initLayout()
    {
    	score_board = (TextView) findViewById(R.id.score);
    	level_board = (TextView) findViewById(R.id.level_count);
    	next_turn   = (TextView)findViewById(R.id.text);
    	
    	btn1 = (ImageView)findViewById(R.id.btn1);
    	btn2 = (ImageView)findViewById(R.id.btn2);
    	btn3 = (ImageView)findViewById(R.id.btn3);
    	btn4 = (ImageView)findViewById(R.id.btn4);
    	
    	//버튼이 눌리면 usr 리스트에 담겨진 값과 비교하여 정답을 맞췄는지 확인한다
    	//이 부분을 setOnClickListener가 아니라..즉 버튼 눌렸을 때 바로 compare를 호출하는 것이 아니라
    	//버튼을 눌렀다가 떼었을(onKeyUp)때 compare를 호출하도록 수정해야한다.
    	btn1.setOnTouchListener(new View.OnTouchListener(){
			@Override
			public boolean onTouch(View arg0, MotionEvent motion) {
				switch(motion.getAction())
				{
					case MotionEvent.ACTION_UP:
						compare(BUTTON_1);
						break;
				}
				return false;
			}
    		
    	});
    	
    	btn2.setOnTouchListener(new View.OnTouchListener(){
			@Override
			public boolean onTouch(View arg0, MotionEvent motion) {
				switch(motion.getAction())
				{
					case MotionEvent.ACTION_UP:
						compare(BUTTON_2);
						break;
				}
				return false;
			}
    		
    	});
    	
    	btn3.setOnTouchListener(new View.OnTouchListener(){
			@Override
			public boolean onTouch(View arg0, MotionEvent motion) {
				switch(motion.getAction())
				{
					case MotionEvent.ACTION_UP:
						compare(BUTTON_3);
						break;
				}
				return false;
			}
    		
    	});
    	
    	btn4.setOnTouchListener(new View.OnTouchListener(){
			@Override
			public boolean onTouch(View arg0, MotionEvent motion) {
				switch(motion.getAction())
				{
					case MotionEvent.ACTION_UP:
						compare(BUTTON_4);
						break;
				}
				return false;
			}
    		
    	});
    	
/*    	btn1.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View arg0) {
				compare(BUTTON_1);
			}		
		});
    	
		btn2.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View arg0) {
				compare(BUTTON_2);
			}
		});
		
		btn3.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View arg0) {
				compare(BUTTON_3);
			}
		});
		
		btn4.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View arg0) {
				compare(BUTTON_4);				
			}
		});*/
    	
    	startBtn = (Button)findViewById(R.id.startbtn);

    	//게임 시작
    	startBtn.setOnClickListener(new View.OnClickListener() {
			
    		//이 아래 는 내가 invalidateOptionsMenu를 써줬더니 에러가 나서
    		//SupperessLint를 썼더니 에러가 없어져서 쓴거임
			@SuppressLint("NewApi")
			@Override
			public void onClick(View arg0) {
				settingOrder();   //난수 발생시키는 함수 
				if(saveOrderOfCom != null && saveOrderOfCom.size() > 0)
				{
					startBtn.setVisibility(View.INVISIBLE);    //게임이 시작되면 스타트 버튼 사라짐.
					next_turn.setText(R.string.computer_turn);
					startThread();  //발생시킨 난수의 값대로 버튼이 눌려지는 모양을 표현하는 쓰레드 호출
					
					//메뉴 설정 
					//start버튼이 보이면 메뉴에 new game이 보이지 않고
					//start버튼이 보이지 않으면 (게임이 시작되면) 메뉴에 new game이 보이도록 메뉴를 생성하는 함수를 동적으로 호출 
					invalidateOptionsMenu();
				}
				
			}
		});
    }
    
    //점수 및 배열 등 초기화 
    @SuppressLint("NewApi")
	private void initScore()
    {
    	level_count = 1;
    	score = 0;
    	score_board.setText(score+"");
    	level_board.setText(level_count+"");
    	next_turn.setText("");
    	
    	saveOrderOfCom.clear();
    	saveOrderOfUsr.clear();
    	
    	startBtn.setVisibility(View.VISIBLE);
    	setButtonEnable(false);
    	
    	invalidateOptionsMenu();
    }

    //컴퓨터가 버튼을 누르는 모습을 표현하는 동안에는 버튼이 눌리지 않도록 하기 위한 함수 
    private void setButtonEnable(boolean val)
    {
    	btn1.setEnabled(val);
		btn2.setEnabled(val);
		btn3.setEnabled(val);
		btn4.setEnabled(val);
    }
    
    //사용자가 누른 버튼과 컴퓨터가 눌렀던 버튼이 일치하는 체크하는 함수 
    private void compare(int btn)
    {
    	//saveOrderOfUser.get(0) : 컴퓨터가 눌렀던 버튼
    	//btn : 사용자가 누른 버튼
    	//두 값이 동일하면 맞춘거
    	if(saveOrderOfUsr.get(0) == btn)
		{
			score += 20;
			score_board.setText(score+"");
			saveOrderOfUsr.remove(0);  //처음 두값을 확인했으면 지워버린다 그래야 그 다음값이 index가 0으로 변하니까 
			
			//컴퓨터가 누른값과 비교 다 했으면
			if(saveOrderOfUsr != null && saveOrderOfUsr.size() == 0)
			{
				next_turn.setText(R.string.computer_turn);
				level_count++;
				level_board.setText(level_count+"");
				
				settingOrder(); //다시 난수 발생해서 
				
				if(saveOrderOfCom != null && saveOrderOfCom.size() > 0)
				{
					startThread(); //컴퓨터가 버튼을 누르는 쓰레드 시작 
				}
			}
		}
		else  //틀렸을 경우
		{
			new AlertDialog.Builder(this)
			.setTitle("Level " + (level_count - 1))
			.setMessage("Your Score is "+ score +".")
			.setCancelable(false)
			.setPositiveButton("Yes",new DialogInterface.OnClickListener()
			{
				@Override
				public void onClick(DialogInterface dialog, int which)
				{
					initScore(); //게임 초기화 
				}
			}).show();
		}
    }
    
    //레벨카운트만큼 난수를 발생시켜서 배열에 저장 버튼이 4개이므로 난수는 0,1,2,3 중에서 발생하도록
    private void settingOrder()
    {
    	Random random = new Random();
    	for(int i=0; i < level_count; i++)
    	{
    		int num = random.nextInt(3);
    		saveOrderOfCom.add(i,num);
    		saveOrderOfUsr.add(i,num);
    	}
    }
    
    public void startThread()
    {
    	PushThread mthread = new PushThread(); 
    	setButtonEnable(false); //사용자가 버튼 못누르게 설정

    	//일단 시작전에 sleep을 줌.. 이건..글로 설명하기 힘듬...보여줘야 함..
    	//여튼 텀이 있어야함.
/*    	try{
			Thread.sleep(200);
		}catch(InterruptedException e)
		{
			e.printStackTrace();
		}
*/		
		//배열에 값을 하나씩 차례대로 읽어서 먼저 눌러줌.
    	switch(saveOrderOfCom.get(0))
    	{
	    	case BUTTON_1:
	    		btn1.setPressed(true);
	    		Log.e("우너지","누름1");
	    		break;
	    	case BUTTON_2:
	    		btn2.setPressed(true);
	    		Log.e("우너지","누름2");
	    		break;
	    	case BUTTON_3:
	    		btn3.setPressed(true);
	    		Log.e("우너지","누름3");
	    		break;
	    	case BUTTON_4:
	    		btn4.setPressed(true);
	    		Log.e("우너지","누름4");
	    		break;
    	}
    	
    	if (pushThread == null)
		{
    		pushThread = new PushThread();
		}

    	pushThread.setBtn(saveOrderOfCom.get(0));
    	saveOrderOfCom.remove(0); //누른값 이제 지워줌 그래야 다음 값을 누를 수 있으니까 
    	pushThread.run();  //쓰레드 돌림 이제 몇 초 쉬러 가는거..
    	
    }
    
    class PushThread extends Thread{
    	ButtonHandler mHandler = new ButtonHandler();
    	
    	int mBtn;
    	
    	//어떤 버튼이 눌렸는지 저장하는 함수 
    	public void setBtn(int btn)
    	{
    		mBtn = btn;
    	}
    	
		@Override
		public void run() {
			try{
				//어떤 버튼이 눌렸는지 정보와 함께 몇 초 쉬어 준다. 눌린채로..
				Message msg = mHandler.obtainMessage(mBtn);
				Log.e("우너지","눌림500");
    			sleep(1500);
    			mHandler.sendMessage(msg);	
    		}
    		catch(InterruptedException e)
    		{
    			e.printStackTrace();
    		}
		}
    	
    }
    
    //버튼이 눌렸다가 원상복귀되고 다음 버튼 눌리기 전까지 몇 초 쉬어줌 
    class PullThread extends Thread{
    	ButtonHandler mHandler = new ButtonHandler();

		@Override
		public void run() {
			try{
				Message msg = mHandler.obtainMessage(STOP_THREAD);
				Log.e("우너지","올림 200");
    			sleep(200);
    			mHandler.sendMessage(msg);	
    		}
    		catch(InterruptedException e)
    		{
    			e.printStackTrace();
    		}
		}
    	
    }
    
    class ButtonHandler extends Handler{

		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);

			//메시지로 들어온 값이 버튼이면 그 버튼을 다시 원상복귀해주고 몇 초간 쉬도록 pullThread 호출
			//메시지로 들어온 값이 버튼이 아니고 STOP_THREAD 이면 다음 버튼 누르거나 유어턴으로 바꾸어 줌 
			switch(msg.what)
			{
				case BUTTON_1:
					btn1.setPressed(false);
					Log.e("우너지","올림1");
					if (pullThread == null)
					{
						pullThread = new PullThread();
					}
					pullThread.run();
					break;
				case BUTTON_2:
					btn2.setPressed(false);
					Log.e("우너지","올림2");
					if (pullThread == null)
					{
						pullThread = new PullThread();
					}
					pullThread.run();
					break;
				case BUTTON_3:
					btn3.setPressed(false);
					Log.e("우너지","올림3");
					if (pullThread == null)
					{
						pullThread = new PullThread();
					}
					pullThread.run();
					break;
				case BUTTON_4:
					btn4.setPressed(false);
					Log.e("우너지","올림4");
					if (pullThread == null)
					{
						pullThread = new PullThread();
					}
					pullThread.run();
					break;
				case STOP_THREAD:
					//다음 버튼 누를게 있으면 
					if(saveOrderOfCom != null && saveOrderOfCom.size() > 0)
					{
						startThread();
					}
					else // 다 눌렀으면 your_turn
					{
						setButtonEnable(true);
						next_turn.setText(R.string.your_turn);
					}
					break;
			}
		}
    }

    
    //상황에 맞게 메뉴를 바꿔 주기 위해서 사용한 함수
    //게임이 시작되면 메뉴가 생기고
    //게임이 시작되기 전에는 메뉴가 없다.
	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		
		menu.clear();
		if(startBtn.getVisibility() == View.INVISIBLE)
		{
			menu.add(0, NEW_GAME_ID, 0 ,R.string.new_game);
		}
		return true;
	}
	
	//메뉴 눌렀을 떄 어떤 함수 실행할 것인지
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch(item.getItemId())
		{
			case NEW_GAME_ID:
				initScore();
				break;
		}
		return true;
	}

	
	//게임 도중 백키 누르면 다이얼로그 나오도록 
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		
		switch(keyCode)
		{
		 	case KeyEvent.KEYCODE_BACK:
		 		new AlertDialog.Builder(this)
				.setTitle("Finish")
				.setMessage("Do you want to finish?")
				.setCancelable(false)
				.setPositiveButton("Yes",new DialogInterface.OnClickListener()
				{
					@Override
					public void onClick(DialogInterface dialog, int which)
					{
						finish();
					}
				})
				.setNegativeButton("No",new DialogInterface.OnClickListener()
				{
					@Override
					public void onClick(DialogInterface dialog, int which)
					{

					}
				}).show();
			break;
		}
		
		return super.onKeyDown(keyCode, event);
	}

	
	@Override
	protected void onDestroy() {
		super.onDestroy();

		saveOrderOfCom = null;
		saveOrderOfUsr = null;
	}
}
